package com.acdc.utils;

import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class SignUtils {

    /**
     * 生成微信JSAPI支付签名（V2版本）
     * 用于前端chooseWXPay调用
     */
    public static String sign(String merchantId, String appId, String timeStamp, String nonceStr, String packageStr) {
        try {
            // 读取商户私钥
            PrivateKey privateKey = loadPrivateKey("classpath:cert/apiclient_key.pem");
            
            // 构建签名串 - 按照微信JSAPI支付的要求
            String signatureStr = String.format("%s\n%s\n%s\n%s\n",
                    appId, timeStamp, nonceStr, packageStr);
            
            // 使用SHA256withRSA签名
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(privateKey);
            signature.update(signatureStr.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成微信JSAPI支付签名（V3版本）
     * 用于微信支付V3 API调用
     */
    public static String signV3(String method, String urlPath, String timestamp, String nonceStr, String body, String privateKeyPath) {
        try {
            PrivateKey privateKey = loadPrivateKey(privateKeyPath);
            
            // 构建签名串
            String signatureStr = method + "\n" + urlPath + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
            
            // 使用SHA256withRSA签名
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(privateKey);
            signature.update(signatureStr.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
            throw new RuntimeException("V3签名生成失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证微信支付V3通知签名
     * 使用微信支付平台证书公钥验证RSA签名
     */
    public static boolean verifyV3Notify(String method, String urlPath, String timestamp, String nonceStr, String body, String signature) {
        try {
            // 构建签名串
            String message = method + "\n" + urlPath + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
            
            // 使用微信支付平台证书公钥验证签名
            // 注意：这里需要加载微信支付平台证书的公钥
            PublicKey publicKey = loadWechatPayPublicKey();
            
            Signature sig = Signature.getInstance("SHA256withRSA");
            sig.initVerify(publicKey);
            sig.update(message.getBytes(StandardCharsets.UTF_8));
            
            byte[] signatureBytes = Base64.getDecoder().decode(signature);
            return sig.verify(signatureBytes);
            
        } catch (Exception e) {
            throw new RuntimeException("V3通知签名验证失败: " + e.getMessage(), e);
        }
    }

    /**
     * 验证签名（保留原有方法，用于其他场景）
     */
    public static boolean verify(String data, String nonce, String timestamp, String signature, String apiV3Key) {
        try {
            String message = buildMessage(nonce, timestamp, data);
            String expectedSignature = generateSignature(message, apiV3Key);
            return expectedSignature.equals(signature);
        } catch (Exception e) {
            throw new RuntimeException("签名验证失败", e);
        }
    }

    private static String buildMessage(String nonce, String timestamp, String data) {
        return timestamp + "\n" + nonce + "\n" + data + "\n";
    }

    private static String generateSignature(String message, String key) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(signData);
    }

    /**
     * 加载私钥
     */
    private static PrivateKey loadPrivateKey(String filename) throws Exception {
        if (filename.startsWith("classpath:")) {
            // 处理 classpath 资源
            String classPath = filename.substring("classpath:".length());
            Resource resource = new ClassPathResource(classPath);
            try (InputStream inputStream = resource.getInputStream()) {
                return PemUtil.loadPrivateKey(inputStream);
            }
        } else {
            // 处理文件路径
            return PemUtil.loadPrivateKey(new FileInputStream(filename));
        }
    }

    /**
     * 加载微信支付平台证书公钥
     */
    private static PublicKey loadWechatPayPublicKey() throws Exception {
        // 这里应该加载微信支付平台证书的公钥
        // 可以从配置文件或证书文件中加载
        String certPath = "classpath:cert/wechatpay_cert.pem";
        
        if (certPath.startsWith("classpath:")) {
            String classPath = certPath.substring("classpath:".length());
            Resource resource = new ClassPathResource(classPath);
            try (InputStream inputStream = resource.getInputStream()) {
                return PemUtil.loadCertificate(inputStream).getPublicKey();
            }
        } else {
            try (InputStream inputStream = new FileInputStream(certPath)) {
                return PemUtil.loadCertificate(inputStream).getPublicKey();
            }
        }
    }
}

